/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "transmission.h"

#include "common.h"
#include "session.h"
#include "softbus_common.h"

#define DATA_SIZE 128
static sem_t g_sessionSem;

const char *g_sessionName = "com.huawei.dmsdp.softbus_tool";

int OnSessionOpened(int sessionId, int result)
{
    printf("\n>>>OnSessionOpened sessionId = %d, result = %d.\n", sessionId, result);
    sem_post(&g_sessionSem);
    return 0;
}

void OnSessionClosed(int sessionId)
{
    printf("\n>>>OnSessionClosed sessionId = %d.\n", sessionId);
}

void OnBytesReceived(int sessionId, const void *data, unsigned int dataLen)
{
    printf("\n>>>OnBytesReceived sessionId = %d, data = %s.\n", sessionId, (const char *)data);
}

void OnMessageReceived(int sessionId, const void *data, unsigned int dataLen)
{
    printf("\n>>>OnMessageReceived sessionId = %d, data = %s.\n", sessionId, (const char *)data);
}

void OnStreamReceived(int sessionId, const StreamData *data, const StreamData *ext,
        const StreamFrameInfo *param)
{
    printf("\n>>>OnStreamReceived sessionId = %d, data = %s, ext = %s\n", sessionId, data->buf, ext->buf);
}

static int OnSendFileProcess(int sessionId, uint64_t bytesUpload, uint64_t bytesTotal)
{
    printf("\n>>>OnSendFileProcess sessionId = %d, bytesUpload = %"PRIu64", total = %"PRIu64"\n",
        sessionId, bytesUpload, bytesTotal);
    return 0;
}

static int OnSendFileFinished(int sessionId, const char *firstFile)
{
    printf("\n>>>OnSendFileFinished sessionId = %d, first file = %s\n", sessionId, firstFile);
    return 0;
}

static void OnFileTransError(int sessionId)
{
    printf("\n>>>OnFileTransError sessionId = %d\n", sessionId);
}

void T_SetFileSendListener(void)
{
    IFileSendListener listener = {
        .OnSendFileProcess = OnSendFileProcess,
        .OnSendFileFinished = OnSendFileFinished,
        .OnFileTransError = OnFileTransError,
    };
    int ret = SetFileSendListener(PKG_NAME, g_sessionName, &listener);
    if (ret != 0) {
        printf("SetFileSendListener fail, ret = %d\n", ret);
    }
}

static int OnReceiveFileStarted(int sessionId, const char *files, int fileCnt)
{
    printf("\n>>>OnReceiveFileStarted sessionId = %d, first file = %s, fileCnt = %d\n", sessionId, files, fileCnt);
    return 0;
}

static void OnReceiveFileFinished(int sessionId, const char *files, int fileCnt)
{
    printf("\n>>>OnReceiveFileFinished sessionId = %d, first file = %s, fileCnt = %d\n", sessionId, files, fileCnt);
}

void T_SetFileReceiveListener(void)
{
    IFileReceiveListener listener = {
        .OnReceiveFileStarted = OnReceiveFileStarted,
        .OnReceiveFileFinished = OnReceiveFileFinished,
        .OnFileTransError = OnFileTransError,
    };
    char recvFilePath[DATA_SIZE];
    GetInputString("Please input receive file path:", recvFilePath, DATA_SIZE);
    int ret = SetFileReceiveListener(PKG_NAME, g_sessionName, &listener, recvFilePath);
    if (ret != 0) {
        printf("SetFileReceiveListener fail, ret = %d\n", ret);
    }
}

void T_SendMessage(void)
{
    int sessionId;
    char data[DATA_SIZE];
    sessionId = GetInputNumber("Please input session Id:");
    GetInputString("Please input data to SendMessage:", data, DATA_SIZE);
    int ret = SendMessage(sessionId, data, strlen(data) + 1);
    if (ret != 0) {
        printf("SendMessage fail, ret = %d\n", ret);
    } else {
        printf("SendMessage ok\n");
    }
}

void T_SendBytes(void)
{    
    int sessionId;
    char data[DATA_SIZE];
    sessionId = GetInputNumber("Please input session Id:");
    GetInputString("Please input data to SendBytes:", data, DATA_SIZE);
    int ret = SendBytes(sessionId, data, strlen(data) + 1);
    if (ret != 0) {
        printf("SendBytes fail, ret = %d\n", ret);
    } else {
        printf("SendBytes ok\n");
    }
}

void T_SendStream(void)
{
    int sessionId;
    char data[DATA_SIZE];
    StreamData d1 = {0};
    sessionId = GetInputNumber("Please input session Id:");
    GetInputString("Please input data to SendStream:", data, DATA_SIZE);
    d1.buf = data;
    d1.bufLen = strlen(data) + 1;
    StreamData d2 = {0};
    StreamFrameInfo tmpf = {0};

    int ret = SendStream(sessionId, &d1, &d2, &tmpf);
    if (ret != 0) {
        printf("SendStream fail, ret = %d\n", ret);
    } else {
        printf("SendStream ok\n");
    }
}

void T_SendFile(void)
{
    int sessionId;
    const char *sfileList[1] = { NULL };
    char filePath[DATA_SIZE] = {0};
    sessionId = GetInputNumber("Please input session Id:");
    GetInputString("Please input file path to SendFile:", filePath, DATA_SIZE);
    sfileList[0] = filePath;
    int32_t ret = SendFile(sessionId, sfileList, NULL, 1);
    if (ret != 0) {
        printf("SendFile fail, ret = %d\n", ret);
    } else {
        printf("SendFile ok\n");
    }
}

void T_CreateSessionServer(void)
{
    ISessionListener listener = {
        .OnSessionOpened = OnSessionOpened,
        .OnSessionClosed = OnSessionClosed,
        .OnBytesReceived = OnBytesReceived,
        .OnMessageReceived = OnMessageReceived,
        .OnStreamReceived = OnStreamReceived,
        .OnQosEvent = NULL
    };

    int ret = CreateSessionServer(PKG_NAME, g_sessionName, &listener);
    if (ret != 0) {
        printf("CreateSessionServer fail, ret = %d.\n", ret);
        return;
    }
    printf("CreateSessionServer ok.\n");
}

void T_RemoveSessionServer(void)
{
    int ret = RemoveSessionServer(PKG_NAME, g_sessionName);
    if (ret != 0) {
        printf("RemoveSessionServer fail, ret = %d.\n", ret);
        return;
    }
}

void T_OpenSession(void)
{
    SessionAttribute attr;
    int sessionId;
    char networkId[NETWORK_ID_BUF_LEN];
    (void)memset_s(&attr, sizeof(attr), 0, sizeof(attr));
    
    attr.dataType = GetInputNumber("Please input session type(1 - TYPE_MESSAGE, 2 - TYPE_BYTES, 3 - TYPE_FILE, 4 - TYPE_STREAM):");
    if (attr.dataType == TYPE_STREAM) {
        attr.attr.streamAttr.streamType = RAW_STREAM;
    }

    attr.linkTypeNum = GetInputNumber("Please input linkType num(0 - AUTO or [1, 4]):");
    if (attr.linkTypeNum < 0 || attr.linkTypeNum > LINK_TYPE_MAX) {
        printf("invalid linkType num = %d.", attr.linkTypeNum);
        return;
    }
    for (int i = 0; i < attr.linkTypeNum; i++) {
        printf("Please input linkType[%d]", i);
        attr.linkType[i] = GetInputNumber("(1 - WLAN 5G, 2 - WLAN 2G, 3 - WIFI P2P, 4 - BR):");
    }

    GetInputString("Please input network Id:", networkId, NETWORK_ID_BUF_LEN);
    sem_init(&g_sessionSem, 0, 0);
    sessionId = OpenSession(g_sessionName, g_sessionName, networkId, "", &attr);
    if (sessionId < 0) {
        printf("OpenSession fail, sessionId = %d\n", sessionId);
        sem_destroy(&g_sessionSem);
        return;
    }
    sem_wait(&g_sessionSem);
    printf("OpenSession succ, sessionId = %d\n", sessionId);
    sem_destroy(&g_sessionSem);
}

void T_CloseSession(void)
{
    int sessionId = GetInputNumber("Please input session Id to CloseSession:");
    CloseSession(sessionId);
}